package com.miniserver.tql.impl;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.commons.lang.StringUtils;

import com.miniserver.tql.TqlMaster;
import com.miniserver.util.DKeyDesEncrypt;
import com.miniserver.util.LogUtil;

/**
 * 实现原始数据库同多个Memdb实例同步
 */
public class HsqlDataSync {
	private TqlMaster tqlMaster;
	private String memdbName;
	private String sqlPath;
	private long syncId = 0;
	private String syncIdHolder = "$actionid$";
	//
	private static LogUtil log = LogUtil.getLogUtil("HsqlDataSync");
	private static final int SYNC_THREAD_COUNT = 1;
	private ExecutorService threadPool;
	private CompletionService<HsqlTableSyncResult> completionService;
	private List<String[]> syncTablesInfo = new ArrayList<String[]>();
	private int syncTableCount=0;
	// 调试模式
	private boolean isDebug = true;

	public boolean isDebug() {
		return isDebug;
	}

	public void setDebug(boolean isDebug) {
		this.isDebug = isDebug;
	}

	public HsqlDataSync(TqlMaster tqlMaster, String memdbName, String sqlPath, String syncIdHolder, long syncId) {
		this.tqlMaster = tqlMaster;
		this.memdbName = memdbName;
		this.sqlPath = sqlPath;
		this.syncId = syncId;
		this.syncIdHolder = syncIdHolder;
		//
		this.threadPool = Executors.newFixedThreadPool(SYNC_THREAD_COUNT);
		this.completionService = new ExecutorCompletionService<HsqlTableSyncResult>(this.threadPool);
	}

	/**
	 * 同步
	 * 
	 * @return
	 */
	public boolean sync() throws Exception {
		// 初始化map
		initSyncSqls();
		if (this.syncTablesInfo.isEmpty()) {
			return false;
		}
		// 遍历，添加任务
		for (String[] tableInfo : this.syncTablesInfo) {
			String syncSQL = tableInfo[0];
			String tableName = tableInfo[1];
			String primaryKey = tableInfo[2];
			String physicaldb = tableInfo[3];
			String if_sync=tableInfo[4];
			/**
			 * 1 syncid=0 :都进行同步，同步时忽略actionid。
			 * 2 syncid>0 ：如果if_sync=false，则不进行 “运行中同步,如果if_sync=true,同步。
			 */
			if(syncId>0 && if_sync.equals("false")){
				continue;
			}
			HsqlTableSyncTask task = new HsqlTableSyncTask(this.tqlMaster, this.memdbName, physicaldb, tableName,
					syncSQL, primaryKey, this.syncIdHolder, this.syncId);
			task.setIsDebug(isDebug);
			if (!threadPool.isShutdown()) {
				completionService.submit(task);
				syncTableCount+=1;
			}
		}
		return getResult();
	}

	/**
	 * 初始化sql语句map
	 */
	private void initSyncSqls() throws Exception {
		File sqlFile = new File(sqlPath);
		ByteArrayInputStream input = new ByteArrayInputStream(DKeyDesEncrypt.decryptFileToBytes(sqlFile));
		BufferedReader br = new BufferedReader(new InputStreamReader(input));
		String data = null;
		while (StringUtils.isNotBlank(data = br.readLine())) {
			if (data.startsWith("--")) {
				continue;
			}
			//
			String[] dataLine = data.split("@@@");
			if (dataLine.length < 2) {
				continue;
			}
			String[] info = new String[5];
			if(dataLine.length==3){
				info[4] = dataLine[1].toLowerCase(); //是否定时同步
				info[0] = dataLine[2]; // SQL
			}else{
				info[4] = "false";
				info[0] = dataLine[1]; // SQL
			}
			
			String[] ss = dataLine[0].split("@");
			info[1] = ss[0]; // TABLE_NAME
			if (ss.length > 2) {
				info[2] = ss[1];// PrimaryKey
				info[3] = ss[2];// PhysicalDb
			} else if (ss.length == 2) {
				info[2] = ss[1];
				info[3] = this.memdbName;
			} else {
				info[2] = "id";
				info[3] = this.memdbName;
			}
			this.syncTablesInfo.add(info);
		}
		br.close();
	}

	/**
	 * 返回结果
	 * 
	 * @return
	 */
	private boolean getResult() {
		List<HsqlTableSyncResult> list = new ArrayList<HsqlTableSyncResult>();
		for (int i = 0; i != syncTableCount; i++) {
			try {
				HsqlTableSyncResult taskRtn = completionService.take().get();
				list.add(taskRtn);
			} catch (Exception e) {
				log.error("getResult", e);
			}
		}
		//
		boolean result = true;
		for (HsqlTableSyncResult temp : list) {
			if (!temp.getSuccess()) {
				if (isDebug) {
					log.debug("	数据表" + temp.getName() + "初始化失败。");
				}
				result = temp.getSuccess();
				break;
			}
		}
		return result;
	}

	/**
	 * 关闭
	 */
	public void close() {
		if (threadPool != null) {
			threadPool.shutdown();
		}
	}
}